function varargout = TLUnitDelayDlg(action, varargin)

% TL_UNITDELAY_DLG manages the user interface for TargetLink Unit Delay block
%
% SYNTAX dlgInfo = TLUnitdelayDlg('GetDlgInfo');
%   gets dialog info of TargetLink Unit Delay block
%
%   INPUT ARGUMENTS
%   -/-      
%
%   OUTPUT ARGUMENTS
%   dlgInfo     dialog information contains pageNames etc.
%
% SYNTAX [sheetDims, ctrlPos] = TLUnitdelayDlg('CtrlPositions', pageName, commonGeom, dlgInfo, sheetDims);
%   calculates the control positions of all controls of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   commonGeom      common geometry data
%   dlgInfo         dialog information contains pageNames etc.
%   sheetDims       dimension of sheet
%
%   OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% SYNTAX dlgdata = TLUnitdelayDlg('Create', pageName, dlgfig, dlgdata);
%   creates all controls of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   dlgfig          figure handle
%   dlgdata         dialog data
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%
% SYNTAX [dlgdata,bModified] = TLUnitdelayDlg('Manage', pageName, dlgfig, dlgdata, pageAction);
%   manages all actions of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   dlgfig          figure handle
%   dlgdata         dialog data
%   pageAction      modified control of current page
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%   bModified       flag = 1, if dialog data are modified, =0 otherwise
%
% SYNTAX dlgdata = TLUnitdelayDlg('Update', dlgfig, dlgdata, pageNum);
%   updates all controls of dialog page: <pageNum>
%
%   INPUT ARGUMENTS
%   dlgfig          figure handle
%   dlgdata         dialog data
%   pageNum         number of current page
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%
% SYNTAX TLUnitdelayDlg('Apply', dlgfig, dlgdata);
%   writes current blockdata to block and DD
%
%   INPUT ARGUMENTS
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
%   OUTPUT ARGUMENTS
%   - / -


% Author(s): D. Andoleit, T. Pietzsch
% $RCSfile: TLUnitdelayDlg.m $
% $ProjectName: e:/ARC/Components/HostSW/SimulinkBlocksets/TLBlocksets/CommonBlockset/CommonBlockset_SimBlocksUI/Sources/MSrc/project.pj $
% $Revision: 1.26 $
% $Date: 2011/07/21 14:48:45MESZ $
%
% Copyright ?2011 dSPACE GmbH. All rights reserved.


switch action
    case 'GetDlgInfo'
        hBlock = varargin{1};
        dlgInfo = tl_get_dlginfodefaults('tlsim');
        titleName = 'Unit Delay';
        pathinfo = tl_pathinfo(hBlock);
        dlgInfo.title = sprintf('TargetLink %s: %s', titleName, pathinfo.shortDisplayName);
        dlgInfo.pageNames   = {
            'Output'...
            'State'...
            'Logging & Autoscaling'...
            'Documentation'};
        varargout{1} = dlgInfo;
        varargout{2} = get_tlcg_data(hBlock);

    case 'CtrlPositions'
        pageName     = varargin{1};
        commonGeom   = varargin{2};
        sheetDims    = varargin{4};
        switch pageName
            case 'Output'
                [sheetDims, ctrlPos] = ...
                    FcnCalcOutputControlPositions(commonGeom);
            case 'State'
                [sheetDims, ctrlPos] = FcnCalcStateControlPositions(commonGeom);
            case 'Logging & Autoscaling'
                excludedCtrls = {'keepParameter'};
                [sheetDims, ctrlPos] = ...
                    TLManageLoggingCtrls('calcCtrls', commonGeom, sheetDims, excludedCtrls);
            case 'Documentation'
                bTblBlock = 0;
                bCodeComment = 1;
                [sheetDims, ctrlPos] = ...
                    TLManageDocCtrls('ctrlpos', commonGeom, sheetDims, bCodeComment, bTblBlock);
        end
        varargout{1} = sheetDims;
        varargout{2} = ctrlPos;

    case 'Create',
        pageName = varargin{1};
        dlgfig   = varargin{2};
        dlgdata  = varargin{3};
        pageNum  = strmatch(pageName,dlgdata.pageNames, 'exact');

        switch pageName
            case 'Output'
                dlgdata = FcnCreateOutputControls(pageNum, dlgfig, dlgdata);
            case 'State'
                dlgdata = FcnCreateStateControls(pageNum, dlgfig, dlgdata);
            case 'Logging & Autoscaling'
                % set bCheckLogging, because block supports bus signals
                dlgdata.pageData{pageNum}.bCheckLogging = 1;
                dlgdata = TLManageLoggingCtrls('create', pageNum, dlgfig, dlgdata);
            case 'Documentation'
                dlgdata = TLManageDocCtrls('create', pageNum, dlgfig, dlgdata);
        end
        dlgdata.pageData{pageNum}.ctrlPos = [];
        varargout{1} = dlgdata;

    case 'Manage',
        pageName   = varargin{1};
        dlgfig     = varargin{2};
        dlgdata    = varargin{3};
        pageAction = varargin{4};
        pageNum    = strmatch(pageName,dlgdata.pageNames,'exact');
        switch pageName
            case 'Output'
                [dlgdata, bModified] = FcnManageOutputControls( ...
                    pageNum, dlgfig, dlgdata, pageAction);
            case 'State'
                [dlgdata,bModified] = FcnManageStateControls( ...
                    pageNum, dlgfig, dlgdata, pageAction);
            case 'Logging & Autoscaling'
                [dlgdata, bModified] = ...
                    TLManageLoggingCtrls('manage', pageNum, dlgdata, pageAction, 'logdata');
            case 'Documentation'
                [dlgdata, bModified] = TLManageDocCtrls( ...
                    'callback', pageNum, dlgfig, dlgdata, pageAction);
        end
        varargout{1} = dlgdata;
        varargout{2} = bModified;

    case 'ManageSystemIcons',
        dlgfig     = varargin{1};
        dlgdata    = varargin{2};
        pageAction = varargin{3};
        [dlgdata, bModified] = FcnManageSystemIcons(dlgfig,dlgdata,pageAction);
        varargout{1} = dlgdata;
        varargout{2} = bModified;

    case 'Update'
        dlgfig   = varargin{1};
        dlgdata  = varargin{2};
        pageNum  = varargin{3};
        pageName = dlgdata.pageNames{pageNum};

        switch pageName
            case 'Output'
                dlgdata = FcnUpdateOuputControls(dlgdata, dlgfig, pageNum);
            case 'State'
                dlgdata = FcnUpdateStateControls(dlgdata, dlgfig, pageNum);
            case 'Logging & Autoscaling'
                dlgdata =  TLManageLoggingCtrls('update',pageNum,dlgdata,'logdata','output');
                TLManageLoggingCtrls('setCtrls',pageNum, dlgfig, dlgdata);
            case 'Documentation'
                TLManageDocCtrls('update', pageNum, dlgfig, dlgdata);
        end
        varargout{1} = dlgdata;

    case 'Apply'
        dlgdata  = varargin{2};
        bClose   = varargin{3};
        [dlgdata, bClose] = tl_apply_blockdata(dlgdata, bClose);
        varargout{1} = dlgdata;
        varargout{2} = bClose;

    otherwise
        error(['Invalid action: "' action '"']);
end


%-----------------------------------------------------------------------------------------
% FcnManageSystemIcons manage actions of toolbar icons
%
% INPUT ARGUMENTS
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%   action      action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageSystemIcons(dlgfig, dlgdata, action) %#ok

bModified = false;
switch action
    case 'EditCode'
        % look for associated production code file
        [codefile,blockstr] = get_codefile(dlgdata.model);
        if ~isempty(codefile)
            codeedit(codefile,blockstr);
        end

    case 'ViewCode'
        switch dlgdata.pageNames{dlgdata.CurrentPageNum}
            case 'State'
                blockVar = 'state';
            otherwise
                blockVar = 'output';
        end
        tl_create_links_to_model('ShowComputation',dlgdata.model, blockVar);

    otherwise
        error('Invalid callback');

end % switch(action)


%-----------------------------------------------------------------------------------------
% FcnCalcOutputControlPositions calculates positions for all controls on output page
%
% INPUT ARGUMENTS
%   commonGeom      common geometrie information
%
% OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% HINT:
% Positions are calculated from the bottom left of the figure to avoid
% dependencies on figure size
%-----------------------------------------------------------------------------------------
function [sheetDims, ctrlPos] = FcnCalcOutputControlPositions(commonGeom)

excludedCtrls = {};
[sheetDims, ctrlPos, col] = ...
    tl_calc_ctrls_positions(commonGeom, excludedCtrls);

sampleTimeLabelSize = ds_get_uicontrol_sizes(commonGeom, ...
    {'Sample Time:', 'text'});

cx = col(1);
cy = commonGeom.frameBottomEdgeBuffer;
ctrlPos.sampleTimeLabel = [cx cy sampleTimeLabelSize];

cx = col(2);
ctrlPos.sampleTimeEdit = [cx cy ctrlPos.varEdit(3:4)];

sheetDims(2) = sheetDims(2) ...
    + ctrlPos.addoptGroupbox(4) ...
    + commonGeom.textHeight;


%-----------------------------------------------------------------------------------------
% FcnCreateOutputControls creates the figure window
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%-----------------------------------------------------------------------------------------
function dlgdata = FcnCreateOutputControls(pageNum, dlgfig, dlgdata)

% create standard controls
dlgdata = TLManageVariableCtrls('create', pageNum, dlgfig, dlgdata);
dlgdata = TLManageScalingCtrls('create', pageNum, dlgfig, dlgdata);

Children = dlgdata.pageData{pageNum}.children;
ctrlPos  = dlgdata.pageData{pageNum}.ctrlPos;
pageName = dlgdata.pageNames{pageNum};
% create the addoptGroupbox which will contain sample time
Children.addoptGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Sample time'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.addoptGroupbox);

Children.sampleTimeLabel = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'text', ...
    'String',             'Sample time:', ...
    'Position',           ctrlPos.sampleTimeLabel);

Children.sampleTimeEdit = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'BackgroundColor',    'w', ...
    'Style',              'edit', ...
    'Position',           ctrlPos.sampleTimeEdit, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''sampleTimeEdit'')',pageName));

dlgdata.pageData{pageNum}.children = Children;


%-----------------------------------------------------------------------------------------
% FcnManageOutputControls manage control actions of output page
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%   pageAction  action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageOutputControls(pageNum, dlgfig, dlgdata, pageAction)

Children  = dlgdata.pageData{pageNum}.children;

switch pageAction
    case 'sampleTimeEdit'
        sampleTimeStr = tl_deblank(get(Children.sampleTimeEdit, 'String'),2);
        if ~isempty(sampleTimeStr)
            dlgdata.data.dt = sampleTimeStr;
        else
            beep;
        end
        bModified = true;

    otherwise
        [dlgdata, bModified1] = ...
            TLManageVariableCtrls('manage', pageNum, dlgfig, dlgdata, pageAction, 'output');
        [dlgdata, bModified2] = ...
            TLManageScalingCtrls('manage', pageNum, dlgfig, dlgdata, pageAction, 'output');
        bModified = bModified1 || bModified2;
end


%--------------------------------------------------------------------------
% FcnUpdateOuputControls updates the controls of the output tab
%
% INPUT ARGUMENTS
%   dlgdata     dialog data
%   dlgfig      figure handle of dialog
%   pageNum     page Number
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%--------------------------------------------------------------------------
function dlgdata = FcnUpdateOuputControls(dlgdata,dlgfig,pageNum)

% update standard controls
dlgdata = TLManageVariableCtrls('update', pageNum, dlgdata, 'output');
dlgdata = TLManageScalingCtrls('update', pageNum, dlgdata, 'output', []);

sampleTimeEditCtrlStatus = struct('enable', 'on', ...
    'string', dlgdata.data.dt);

ctrl = dlgdata.pageData{pageNum}.children.sampleTimeEdit;
UserData = get(ctrl, 'UserData');
UserData.ctrlStatus = sampleTimeEditCtrlStatus;
set(ctrl, 'UserData', UserData);

% set controls
TLManageVariableCtrls('setCtrls', pageNum, dlgfig, dlgdata);
TLManageScalingCtrls('setCtrls', pageNum, dlgfig, dlgdata);
TLSetCtrlsStatus(dlgfig, dlgdata.pageData{pageNum}.children, ...
    {'sampleTimeEdit'});


%-----------------------------------------------------------------------------------------
% FcnCalcStateControlPositions calculates positions for all controls on state page
%
% INPUT ARGUMENTS
%   commonGeom      common geometrie information
%
% OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% HINT:
% Positions are calculated from the bottom left of the figure to avoid
% dependencies on figure size
%-----------------------------------------------------------------------------------------
function [sheetDims, ctrlPos] = FcnCalcStateControlPositions(commonGeom)

excludedCtrls = {'type', 'scaling', 'width', 'element', ...
    'inheritproperties', 'allscaling', 'scalarExp'};
[sheetDims, ctrlPos, col, colDelta, rowDelta] = ...
    tl_calc_ctrls_positions(commonGeom, excludedCtrls);

% floating point options (initial condition and stepsize) controls
strings_and_styles = {'Initial condition:', 'text'; ...
    'Use value of Data Dictionary variable', 'checkbox'};

[initialLabelSize, useDDValueCheckboxSize] = ds_get_uicontrol_sizes(commonGeom, strings_and_styles);

% define new height for addoptGroupbox
ctrlPos.addoptGroupbox(4) = commonGeom.editHeight ...
    + commonGeom.checkboxHeight ...
    + rowDelta ...
    + commonGeom.frameBottomEdgeBuffer ...
    + commonGeom.frameTopEdgeBuffer;

%---------------------------------------
% 2nd row
cy = commonGeom.frameBottomEdgeBuffer;

% ddv checkbox
cx = col(1) + initialLabelSize(1) + fix(colDelta / 3);
ctrlPos.useDDValueCheckbox = [cx, cy, useDDValueCheckboxSize];

%---------------------------------------
% 1st row
cy = cy + commonGeom.checkboxHeight + rowDelta;

% initial value label
cx = col(1);
ctrlPos.initialLabel = [cx cy initialLabelSize];

% initial condition edit field
cx = cx + initialLabelSize(1) + fix(colDelta / 3);
ctrlPos.initialEdit = [cx cy ctrlPos.varEdit(3:4)];

% increase sheet dimensions
sheetDims(2) = sheetDims(2) ...
    + ctrlPos.addoptGroupbox(4);


%-----------------------------------------------------------------------------------------
% FcnCreateStateControls creates state page
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%-----------------------------------------------------------------------------------------
function dlgdata = FcnCreateStateControls(pageNum, dlgfig, dlgdata)

% invoke standard function to create scaling controls
dlgdata = TLManageVariableCtrls('create', pageNum, dlgfig, dlgdata);
% no scaling controls

Children = dlgdata.pageData{pageNum}.children;
ctrlPos = dlgdata.pageData{pageNum}.ctrlPos;
pageName = dlgdata.pageNames{pageNum};
% modify panel title
set(dlgdata.pageData{pageNum}.children.tlcgoptGroupbox, 'Title', 'State options');

% create the addoptGroupbox which will contain initial condition
Children.addoptGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Initial condition'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.addoptGroupbox);

% output initial value controls
Children.initialLabel = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'text', ...
    'String',             'Initial condition:', ...
    'Position',           ctrlPos.initialLabel);

Children.initialEdit = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'BackgroundColor',    'w', ...
    'Style',              'edit', ...
    'Position',           ctrlPos.initialEdit, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''initialEdit'')',pageName));

Children.useDDValueCheckbox = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'checkbox', ...
    'String',             'Use value of Data Dictionary variable', ...
    'Position',           ctrlPos.useDDValueCheckbox, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''useDDValueCheckbox'')',pageName));

dlgdata.pageData{pageNum}.children = Children;


%-----------------------------------------------------------------------------------------
% FcnManageStateControls manage control actions of state page
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%   pageAction  action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageStateControls(pageNum, dlgfig, dlgdata, pageAction)

Children = dlgdata.pageData{pageNum}.children;

switch pageAction
    case 'initialEdit'
        initialStr = deblank(get(Children.initialEdit, 'String'));
        if ~isempty(initialStr)
            if strcmp(initialStr, 'ddv')
                if isempty(dlgdata.data.state.variable)
                    beep;
                else
                    dlgdata.data.state.initial = ['ddv(''', dlgdata.data.state.variable, ''')'];
                    dlgdIata.data.state.useddvariablevalue = true;
                end
            else
                dlgdata.data.state.initial = initialStr;
            end
        else
            beep;
        end
        bModified = true;

    case 'useDDValueCheckbox'
        if get(Children.useDDValueCheckbox, 'Value')
            dlgdata.data.state.initial = ['ddv(''', dlgdata.data.state.variable, ''')'];
            dlgdata.data.state.useddvariablevalue = true;
        else
            dlgdata.data.state.useddvariablevalue = false;
        end
        bModified = true;

    otherwise
        [dlgdata, bModified] = TLManageVariableCtrls( ...
            'manage', pageNum, dlgfig, dlgdata, pageAction, 'state');
end


%-----------------------------------------------------------------------------------------
% FcnUpdateStateControls updates the controls of the state tab
%
% INPUT ARGUMENTS
%   dlgdata     dialog data
%   dlgfig      figure handle of dialog
%   pageNum     page Number
%
% OUTPUT ARGUMENTS
%   dlgdata     dialog data
%-----------------------------------------------------------------------------------------

function dlgdata = FcnUpdateStateControls(dlgdata,dlgfig,pageNum)

Children = dlgdata.pageData{pageNum}.children;


%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
% ANNOTATION * ChristophHo *
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
% State doesn't really have a width and scaling data of its own. So it probably
% doesn't hurt if we just copy it over from the output. We don't really need it
% here, but it saves some special cases.
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dlgdata.data.state.width = dlgdata.data.output.width;
dlgdata.data.state.lsb = dlgdata.data.output.lsb;
dlgdata.data.state.offset = dlgdata.data.output.offset;
dlgdata.data.state.arb = dlgdata.data.output.arb;
dlgdata.data.state.min = dlgdata.data.output.min;
dlgdata.data.state.max = dlgdata.data.output.max;
if isfield(dlgdata, 'extdata') && isfield(dlgdata.extdata, 'output') && ...
        isfield(dlgdata.extdata.output, 'scalarExp')
    dlgdata.extdata.state.scalarExp = dlgdata.extdata.output.scalarExp;
end

dlgdata = TLManageVariableCtrls('update', pageNum, dlgdata, 'state');
[initialValue, constraint, bCompliant] = tl_get_param_constraints( ...
    dlgdata.data.state, dlgdata.extdata.state, 'initial');

% update value field
initialEditCtrlStatus = struct('enable', 'on', 'string', dlgdata.data.state.initial);
if dlgdata.data.state.useddvariablevalue
    initialEditCtrlStatus.enable = 'inactive';
end
initialEditCtrlStatus.iserror = ~bCompliant;

% status of ddv checkbox
useDDValueCheckboxCtrlStatus.enable = flag2str(~isempty(dlgdata.data.state.variable));
useDDValueCheckboxCtrlStatus.value = dlgdata.data.state.useddvariablevalue;
% when Scalar Expansion is switched off on the Output page, assume the initial
% value's width for the output width
dlgdata.extdata.output.defaultwidth = length(initialValue);

% write back control status of extra controls to the controls' UserData property
ctrlsList = { ...
    'initialEdit', ...
    'useDDValueCheckbox'};
for ctrlsNo = 1:length(ctrlsList)
    ctrl = Children.(ctrlsList{ctrlsNo});
    UserData = get(ctrl, 'UserData');
    UserData.ctrlStatus = eval([ctrlsList{ctrlsNo} 'CtrlStatus']);
    set(ctrl, 'UserData', UserData);
end
% set control status of variable, scaling and gain parameter groupbox controls
TLManageVariableCtrls('setCtrls', pageNum, dlgfig, dlgdata);
TLManageScalingCtrls('setCtrls', pageNum, dlgfig, dlgdata);

TLSetCtrlsStatus(dlgfig, Children, ctrlsList);

